package com.addzero.kmp.util

import com.addzero.kmp.processor.entity.JdbcColumnMetadata
import com.addzero.kmp.processor.entity.JdbcTableMetadata
import java.sql.Connection
import java.sql.DatabaseMetaData
import java.sql.DriverManager
import java.sql.ResultSet

/**
 * 数据库元数据工具类
 *
 * 功能：提供数据库元数据提取的通用方法
 */
object DatabaseMetadataUtil {
    /**
     * 创建数据库连接
     *
     * @param driver 数据库驱动类名
     * @param url 数据库连接URL
     * @param username 用户名
     * @param password 密码
     * @return 数据库连接
     */
    fun createConnection(
        driver: String,
        url: String,
        username: String,
        password: String
    ): Connection {
        Class.forName(driver)
        return DriverManager.getConnection(url, username, password)
    }

    /**
     * 提取数据库表元数据
     *
     * @param connection 数据库连接
     * @return 表元数据列表
     */
    fun extractTableMetadata(connection: Connection): List<JdbcTableMetadata> {
        val metaData = connection.metaData
        val tables = mutableListOf<JdbcTableMetadata>()

        // 获取所有表
        metaData.getTables(null, null, "%", arrayOf("TABLE")).use { rs ->
            while (rs.next()) {
                val tableName = rs.getString("TABLE_NAME")
                val schema = rs.getString("TABLE_SCHEM") ?: "public"
                val tableType = rs.getString("TABLE_TYPE")
                val remarks = rs.getString("REMARKS") ?: ""

                // 获取表的所有列
                val columns = extractColumnMetadata(metaData, schema, tableName)
                tables.add(JdbcTableMetadata(
                    tableName = tableName,
                    schema = schema,
                    tableType = tableType,
                    remarks = remarks,
                    columns = columns
                ))
            }
        }
        return tables
    }

    /**
     * 提取表的列元数据
     *
     * @param metaData 数据库元数据
     * @param schema 数据库模式
     * @param tableName 表名
     * @return 列元数据列表
     */
    private fun extractColumnMetadata(
        metaData: DatabaseMetaData,
        schema: String,
        tableName: String
    ): List<JdbcColumnMetadata> {
        val columns = mutableListOf<JdbcColumnMetadata>()
        
        // 获取主键信息
        val primaryKeys = extractPrimaryKeys(metaData, schema, tableName)

        // 获取列信息
        metaData.getColumns(null, schema, tableName, "%").use { rs ->
            while (rs.next()) {
                columns.add(createColumnMetadata(rs, tableName, primaryKeys))
            }
        }
        return columns
    }

    /**
     * 提取表的主键信息
     *
     * @param metaData 数据库元数据
     * @param schema 数据库模式
     * @param tableName 表名
     * @return 主键列名集合
     */
    private fun extractPrimaryKeys(
        metaData: DatabaseMetaData,
        schema: String,
        tableName: String
    ): Set<String> {
        val primaryKeys = mutableSetOf<String>()
        metaData.getPrimaryKeys(null, schema, tableName).use { rs ->
            while (rs.next()) {
                primaryKeys.add(rs.getString("COLUMN_NAME"))
            }
        }
        return primaryKeys
    }

    /**
     * 创建列元数据对象
     *
     * @param rs 结果集
     * @param tableName 表名
     * @param primaryKeys 主键列名集合
     * @return 列元数据对象
     */
    private fun createColumnMetadata(
        rs: ResultSet,
        tableName: String,
        primaryKeys: Set<String>
    ): JdbcColumnMetadata {
        val columnName = rs.getString("COLUMN_NAME")
        val nullableFlag = rs.getString("IS_NULLABLE")
        val nullable = nullableFlag.equals("YES", ignoreCase = true)
        
        return JdbcColumnMetadata(
            tableName = tableName,
            columnName = columnName,
            jdbcType = rs.getInt("DATA_TYPE"),
            columnType = rs.getString("TYPE_NAME"),
            columnLength = rs.getInt("COLUMN_SIZE"),
            nullable = nullable,
            nullableFlag = nullableFlag,
            remarks = rs.getString("REMARKS") ?: "",
            defaultValue = rs.getString("COLUMN_DEF"),
            isPrimaryKey = columnName in primaryKeys
        )
    }
} 